package cn.ichensw.otherworldlystationbackend.service.impl;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.ichensw.otherworldlystationbackend.common.ErrorCode;
import cn.ichensw.otherworldlystationbackend.constant.BangumiConstant;
import cn.ichensw.otherworldlystationbackend.exception.BusinessException;
import cn.ichensw.otherworldlystationbackend.model.dto.bangumi.BangumiSearchFilterRequest;
import cn.ichensw.otherworldlystationbackend.model.dto.bangumi.BangumiSearchRequest;
import cn.ichensw.otherworldlystationbackend.model.dto.bangumi.BangumiSearchV0Request;
import cn.ichensw.otherworldlystationbackend.model.entity.FilmTelevision;
import cn.ichensw.otherworldlystationbackend.model.entity.FilmTelevisionUser;
import cn.ichensw.otherworldlystationbackend.model.entity.User;
import cn.ichensw.otherworldlystationbackend.model.vo.bangumi.*;
import cn.ichensw.otherworldlystationbackend.service.BangumiService;
import cn.ichensw.otherworldlystationbackend.service.FilmTelevisionService;
import cn.ichensw.otherworldlystationbackend.service.FilmTelevisionUserService;
import cn.ichensw.otherworldlystationbackend.service.UserService;
import cn.ichensw.otherworldlystationbackend.utils.RedisUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 豆瓣接口Service实现类
 *
 * @author csw
 */
@Service
@Slf4j
public class BangumiServiceImpl implements BangumiService {
    @Resource
    private UserService userService;
    @Resource
    private FilmTelevisionService filmTelevisionService;
    @Resource
    private FilmTelevisionUserService filmTelevisionUserService;
    @Resource
    private RedisUtils redisUtils;

    @Override
    public Page<BangumiSearchSubjectSmallVO> searchSubject(BangumiSearchRequest request, HttpServletRequest httpServletRequest) {
        if (request == null || request.getKeywords().isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数不能为空");
        }
        List<BangumiSearchSubjectSmallVO> record = new ArrayList<>();

        User loginUser = userService.getLoginUser(httpServletRequest);

        // 请求豆瓣接口，获取响应
        HttpResponse response = HttpRequest.get(BangumiConstant.SEARCH_SUBJECT + request.getKeywords()
                        + "?type=" + request.getType()
                        + "&start=" + request.getStart()
                        + "&max_results=" + request.getMaxResults())
                .execute();
        if (response.getStatus() != HttpStatus.OK.value() || response.body() == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未找到相关影视信息");
        }

        JSONObject jsonObject = JSONUtil.parseObj(response.body());
        jsonObject.getJSONArray("list").forEach(subject -> {
            JSONObject obj = (JSONObject) subject;
            BangumiSearchSubjectSmallVO vo = new BangumiSearchSubjectSmallVO();
            vo.setId(obj.getInt("id"));
            vo.setName(obj.getStr("name_cn"));
            vo.setType(obj.getInt("type"));
            vo.setSummary(obj.getStr("summary"));
            vo.setAirDate(obj.getStr("air_date"));
            vo.setAirWeekday(obj.getStr("air_weekday"));
            vo.setCollection(JSON.parseObject(obj.getStr("collection"), CollectionVO.class));
            vo.setImages(JSON.parseObject(obj.getStr("images"), ImageVO.class));

            Integer value = (Integer) redisUtils.get(String.valueOf(loginUser.getId() + vo.getId()));
            if (value != null) {
                vo.setWatchStatus(value);
            }
            record.add(vo);
        });

        Page<BangumiSearchSubjectSmallVO> pageResult = new Page<>(request.getStart(), request.getMaxResults());
        pageResult.setRecords(record);
        pageResult.setTotal(jsonObject.getInt("total"));
        return pageResult;
    }

    @Override
    public Page<BangumiSearchSubjectSmallVO> searchSubjectV0(BangumiSearchV0Request request, HttpServletRequest httpServletRequest) {
        if (request == null || request.getKeyword().isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数不能为空");
        }
        List<BangumiSearchSubjectSmallVO> record = new ArrayList<>();

        // 构建请求参数
        Map<String, Object> params = new HashMap<>(8);
        params.put("keyword", request.getKeyword());
        params.put("sort", request.getSort());
        // 高级条件搜索
        BangumiSearchFilterRequest filter = request.getFilter();
        List<Integer> typeList = Collections.singletonList(2);
        filter.setType(typeList);

        params.put("filter", filter);

        // 请求豆瓣接口，获取响应
        HttpResponse response = HttpRequest.post(BangumiConstant.SEARCH_SUBJECT_V0 + "?limit=" + request.getLimit() + "&offset=" + request.getOffset())
                .body(JSONUtil.toJsonStr(params), CharsetUtil.UTF_8)
                .execute();
        if (response.getStatus() != HttpStatus.OK.value() || response.body() == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未找到相关影视信息");
        }

        User loginUser = userService.getLoginUser(httpServletRequest);

        JSONObject jsonObject = JSONUtil.parseObj(response.body());

        jsonObject.getJSONArray("data").forEach(subject -> {
            JSONObject obj = (JSONObject) subject;
            log.info("subject:{}", obj);
            BangumiSearchSubjectSmallVO vo = new BangumiSearchSubjectSmallVO();
            vo.setId(obj.getInt("id"));
            vo.setName(obj.getStr("name_cn"));
            vo.setType(obj.getInt("type"));
            vo.setSummary(obj.getStr("summary"));
            vo.setScore(obj.getBigDecimal("score"));
            vo.setAirDate(obj.getStr("date"));
            ImageVO imageVO = new ImageVO();
            imageVO.setMedium(obj.getStr("image"));
            vo.setImages(imageVO);

            Integer value = (Integer) redisUtils.get(String.valueOf(loginUser.getId() + vo.getId()));
            if (value != null) {
                vo.setWatchStatus(value);
            }
            record.add(vo);
        });

        Page<BangumiSearchSubjectSmallVO> pageResult = new Page<>(jsonObject.getLong("offset"), jsonObject.getLong("limit"));
        pageResult.setRecords(record);
        pageResult.setTotal(jsonObject.getInt("total"));
        return pageResult;
    }

    @Override
    public List<BangumiCalendarVO> calendar() {
        List<BangumiCalendarVO> result = new ArrayList<>();

        // 请求豆瓣接口，获取响应
        HttpResponse response = HttpRequest.get(BangumiConstant.CALENDAR)
                .execute();
        if (response.getStatus() != HttpStatus.OK.value() || response.body() == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未找到相关影视信息");
        }
        log.info("response:{}", response.body());

        JSONArray jsonArray = JSONUtil.parseArray(response.body());
        // 遍历每周
        jsonArray.forEach(subject -> {
            JSONObject calendarObj = (JSONObject) subject;
            BangumiCalendarVO calendarVO = new BangumiCalendarVO();
            // 获取 weekday
            List<WeekdayVO> weekdayList = new ArrayList<>();
            WeekdayVO weekday = calendarObj.getBean("weekday", WeekdayVO.class);
            weekdayList.add(weekday);
            // 获取 items
            List<BangumiSearchSubjectSmallVO> items = new ArrayList<>();
            calendarObj.getJSONArray("items").forEach(item -> {
                JSONObject obj = (JSONObject) item;
                BangumiSearchSubjectSmallVO itemVO = new BangumiSearchSubjectSmallVO();
                itemVO.setId(obj.getInt("id"));
                itemVO.setName(obj.getStr("name_cn"));
                itemVO.setType(obj.getInt("type"));
                // summary 基本都是没有的
                itemVO.setSummary(obj.getStr("summary"));
                itemVO.setAirDate(obj.getStr("air_date"));
                itemVO.setAirWeekday(obj.getStr("air_weekday"));
                itemVO.setCollection(JSON.parseObject(obj.getStr("collection"), CollectionVO.class));
                itemVO.setImages(JSON.parseObject(obj.getStr("images"), ImageVO.class));
                items.add(itemVO);
            });
            calendarVO.setItems(items);
            calendarVO.setWeekdays(weekdayList);
            result.add(calendarVO);
        });

        return result;
    }

    @Override
    public BangumiSubjectDetailVO subjectsDetail(Integer subjectId, HttpServletRequest request) {
        if (subjectId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数不能为空");
        }
        Integer dbSubjectId = subjectId + BangumiConstant.bangumiIdPrefix.intValue();
        BangumiSubjectDetailVO result = new BangumiSubjectDetailVO();
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户未登录");
        }
        Long userId = loginUser.getId();

        // 先查询数据库中是否存在该影片
        FilmTelevision filmTelevision = filmTelevisionService.getById(dbSubjectId);
        if (filmTelevision != null) {
            // 数据库中存在，直接返回给前端
            result.setId(filmTelevision.getId());
            result.setName(filmTelevision.getName());
            result.setSummary(filmTelevision.getDescription());
            result.setSubType(filmTelevision.getType());
            result.setTotalEpisodes(filmTelevision.getTotalEpisodes());
            result.setAirDate(DateUtils.format(filmTelevision.getReleaseDate(), "yyyy-MM-dd"));
            result.setAirWeekDate(filmTelevision.getAirWeekDate());
            result.setTags(JSON.parseArray(filmTelevision.getTags(), String.class));
            result.setScore(filmTelevision.getScore());
            result.setImages(JSON.parseObject(filmTelevision.getImages(), ImageVO.class));

            // 查询用户是否收藏了该影片
            FilmTelevisionUser relationEntity = filmTelevisionUserService.lambdaQuery()
                    .eq(FilmTelevisionUser::getFilmId, filmTelevision.getId())
                    .eq(FilmTelevisionUser::getUserId, userId)
                    .one();
            if (relationEntity != null) {
                result.setWatchStatus(relationEntity.getWatchStatus());
            }
            return result;
        }

        // 请求豆瓣接口，获取响应
        HttpResponse response = HttpRequest.get(BangumiConstant.SUBJECT_DETAIL + subjectId)
                .execute();
        if (response.getStatus() != HttpStatus.OK.value() || response.body() == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未找到相关影视信息");
        }

        JSONObject obj = JSONUtil.parseObj(response.body());

        // 手动映射
        result.setTotalEpisodes(obj.getInt("total_episodes"));
        JSONArray infobox = obj.getJSONArray("infobox");
        if (infobox != null) {
            for (Object infoBox : infobox) {
                JSONObject jsonObject = JSONUtil.parseObj(infoBox);
                String key = (String) jsonObject.get("key");
                if (StringUtils.isNotEmpty(key)) {
                    String value = "";
                    switch (key) {
                        case "放送星期":
                            value = (String) jsonObject.get("value");
                            result.setAirWeekDate(value);
                            break;
                        case "官方网站":
                            value = (String) jsonObject.get("value");
                            result.setOfficialWebsite(value);
                            break;
                        case "播放结束":
                            value = (String) jsonObject.get("value");
                            result.setEndDate(value);
                            break;
                        default:
                    }
                }
            }
        }
        JSONArray tagsArray = obj.getJSONArray("tags");
        if (tagsArray != null) {
            List<String> tags = Lists.newArrayList();
            for (Object tagObj : tagsArray) {
                JSONObject jsonObject = JSONUtil.parseObj(tagObj);
                String name = (String) jsonObject.get("name");
                if (StringUtils.isNotEmpty(name)) {
                    tags.add(name);
                }
            }
            result.setTags(tags);
        }
        result.setId(obj.getLong("id") + BangumiConstant.bangumiIdPrefix);
        result.setName(obj.getStr("name_cn"));
        result.setType(obj.getInt("type"));
        result.setAirDate(obj.getStr("date"));
        result.setSummary(obj.getStr("summary"));
        String platform = Optional.ofNullable(obj.getStr("platform")).orElse("");
        if (platform.equals("TV")) {
            result.setSubType("剧集");
        } else {
            // TODO 可能还有别的类型，暂时先判断为这两类
            result.setSubType("电影");
        }
        JSONObject ratingObj = (JSONObject) obj.getObj("rating");
        result.setScore(ratingObj.getBigDecimal("score"));
        JSONObject collection = obj.getJSONObject("collection");
        CollectionVO collectionVO = JSON.parseObject(obj.getStr("collection"), CollectionVO.class);
        collectionVO.setOnHold(collection.getInt("on_hold"));
        result.setCollection(collectionVO);
        result.setImages(JSON.parseObject(obj.getStr("images"), ImageVO.class));

        return result;
    }
}
